package com.fw.system.web.service.impl.v2;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fw.enums.OrderState;
import com.fw.system.web.model.dto.UserDto;
import com.fw.system.web.model.entity.*;
import com.fw.system.web.model.form.v2.OrderManageQuery;
import com.fw.system.web.model.form.v2.ShopAnalyzeQuery;
import com.fw.system.web.model.form.v2.SpuAnalyzeQuery;
import com.fw.system.web.model.vo.v2.*;
import com.fw.system.web.service.*;
import com.fw.system.web.service.v2.V2ShopAnalyzeService;
import com.fw.utils.RandomUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.sql.Wrapper;
import java.text.DateFormat;
import java.util.*;
import java.util.concurrent.CompletionService;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class V2ShopAnalyzeServiceImpl implements V2ShopAnalyzeService {

    @Autowired
    private IFwShopService shopService;

    @Autowired
    private IFwSpuService spuService;

    @Autowired
    private IFwEvaluationService evaluationService;

    @Autowired
    private IFwUsjoinService usjoinService;

    @Autowired
    private IFwFootprintService fwFootprintService;

    @Autowired
    private IFwOrderService orderService;

    @Autowired
    private IFwUcjoinService ucjoinService;

    @Autowired
    private IFwUserService userService;

    @Autowired
    private IFwOfflineService offlineService;

    /**
     * 统计波比量
     * @param shopId
     * @return
     */
    @SneakyThrows
    @Override
    public ShopAnalyzeVo shopAnalyze(String shopId, ShopAnalyzeQuery shopAnalyzeQuery) {
        CompletionService<Object> completionService = ThreadUtil.newCompletionService();

        String yearQuery = shopAnalyzeQuery.getYearQuery();
        ShopAnalyzeVo.ShopAnalyzeVoBuilder builder = ShopAnalyzeVo.builder();
        // 计算 年度 评价
        FwShop shop = shopService.getById(shopId);
        builder.shopSvgCount(shop.getShopScore());
        // 条件保持
        List<FwSpu> spuList = spuService.list(Wrappers.<FwSpu>lambdaQuery().eq(FwSpu::getShopId, shopId));
        Set<String> spuIds = spuList.parallelStream()
                .map(item -> item.getId()).collect(Collectors.toSet());
        // 波比计算，推出 去年的关注量进行比较
        DateTime dateTime = DateUtil.parse(yearQuery, DatePattern.NORM_DATE_FORMAT);
        DateTime offset = dateTime.offset(DateField.YEAR, -1);
        String dataOffsetDate = offset.toString(DatePattern.NORM_DATE_FORMAT);
        //评分
        Future<Object> svgFuture = completionService.submit(() ->   orderSvg(yearQuery, builder, spuList, spuIds));


        // 用户关注量
        Future<Object> svgLikeFuture = completionService.submit(() ->   shopLikeFunc(shopId,yearQuery, builder, dataOffsetDate));


        // 用户来访量
        Future<Object> svgLookFuture = completionService.submit(() ->     shopLookFunc(yearQuery, builder, spuIds, dataOffsetDate));

        Object o = svgFuture.get();
        Object o1 = svgLikeFuture.get();
        Object o2 = svgLookFuture.get();
        return builder.build();
    }

    /**
     *   商品分析管理
     * @param shopId
     * @param spuAnalyzeQuery
     * @return
     */
    @Override
    public SpuAnalyzeVo spuAnalyze(String shopId, SpuAnalyzeQuery spuAnalyzeQuery) {
        SpuAnalyzeVo spuAnalyzeVo = new SpuAnalyzeVo();
        // 条件保持
        String yearQuery = spuAnalyzeQuery.getYearQuery();

        List<FwSpu> spuList = spuService.list(Wrappers.<FwSpu>lambdaQuery().eq(FwSpu::getShopId, shopId));
        Set<String> spuIds = spuList.parallelStream()
                .map(item -> item.getId()).collect(Collectors.toSet());
        // 购买量
        List<FwOrder> spuOrderLists = orderService.list(Wrappers.<FwOrder>lambdaQuery().eq(FwOrder::getShopId, shopId).apply(StringUtils.isNotBlank(yearQuery)," date_format(create_time,'%Y-%m-%d') = {0} ", yearQuery));
        spuAnalyzeVo.setSpuTopVal(spuOrderLists.parallelStream().mapToInt(item -> item.getSpuNumber()).sum());
        //  收藏量
        List<FwUcjoin> ucjoinList = ucjoinService.list(Wrappers.<FwUcjoin>lambdaQuery().in(FwUcjoin::getItemId, spuIds).apply(StringUtils.isNotBlank(yearQuery)," date_format(create_time,'%Y-%m-%d') = {0} ", yearQuery));
        spuAnalyzeVo.setSpuLickVal(ucjoinList.size());
        // 按那个来查询？
        Integer queryFlag = spuAnalyzeQuery.getQueryFlag();
        if (Integer.valueOf(1).equals(queryFlag)){
            // 收藏量 查询  收藏量 排行榜查询
            // spuId  数量
            Map<String, Long> stringLongMap = ucjoinList.parallelStream().map(item -> item.getItemId()).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
            TreeMap<String, Long> treeMap = Maps.newTreeMap();
            stringLongMap.entrySet().stream().sorted(Map.Entry
                            .comparingByValue())
                    .forEachOrdered(b-> treeMap.put(b.getKey(), b.getValue()));

            // 查询 商品
            ArrayList<SpuVo> spuLists = Lists.newArrayList();
            treeMap.forEach((key,val) ->{
                FwSpu spu = spuService.getById(key);
                SpuVo spuVo = new SpuVo();
                BeanUtil.copyProperties(spu,spuVo);
                spuLists.add(spuVo);
            });
            spuAnalyzeVo.setSpuVos(spuLists);
            return spuAnalyzeVo;
        }
        //购买量 查询
        Map<String, Long> stringLongMap = spuOrderLists.parallelStream().map(item -> item.getSpuId()).collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

        TreeMap<String, Long> treeMap = Maps.newTreeMap();
        stringLongMap.entrySet().stream().sorted(Map.Entry
                        .comparingByValue())
                .forEachOrdered(b-> treeMap.put(b.getKey(), b.getValue()));

        // 查询 商品
        ArrayList<SpuVo> spuLists = Lists.newArrayList();
        treeMap.forEach((key,val) ->{
            FwSpu spu = spuService.getById(key);
            SpuVo spuVo = new SpuVo();
            BeanUtil.copyProperties(spu,spuVo);
            spuLists.add(spuVo);
        });
        spuAnalyzeVo.setSpuVos(spuLists);
        return spuAnalyzeVo;
    }

    @Override
    public OrderAnalyzeVo orderAnalyze(UserDto shopDto, ShopAnalyzeQuery shopAnalyzeQuery) {
        OrderAnalyzeVo orderAnalyzeVo = new OrderAnalyzeVo();
        String yearQuery = shopAnalyzeQuery.getYearQuery();
        String shopId = shopDto.getShopId();
        List<FwOrder> fwOrders = orderService.list(Wrappers.<FwOrder>lambdaQuery().eq(FwOrder::getShopId, shopId).apply(StringUtils.isNotBlank(yearQuery), " date_format(create_time,'%Y-%m-%d') = {0} ", yearQuery));
        // 取消 订单 按待支付 状态操作
        orderAnalyzeVo.setCancelOrderVal(fwOrders.parallelStream().filter(item -> OrderState.PENDING_PAYMENT.getCode().equals(item.getStatus())).count());
        orderAnalyzeVo.setOverOrderVal(fwOrders.parallelStream().filter(item -> OrderState.RECEIVED.getCode().equals(item.getStatus())).count());
        orderAnalyzeVo.setWaitOrderVal(fwOrders.parallelStream().filter(item -> OrderState.TO_BE_DELIVERED.getCode().equals(item.getStatus())).count());
        // 统计 订单 金额最高的。
        HashMap<String, BigDecimal> newHashMap = Maps.newHashMap();
        for (FwOrder fwOrder : fwOrders) {
            newHashMap.merge(fwOrder.getUserId(),fwOrder.getTotalPrice(),BigDecimal::add);
        }
        TreeMap<String, BigDecimal> treeMap = Maps.newTreeMap();
        newHashMap.entrySet().stream().sorted(Map.Entry
                        .comparingByValue())
                .forEachOrdered(b-> treeMap.put(b.getKey(), b.getValue()));
        LinkedList<OrderUserAnalyzeVo> userOrderVos = Lists.newLinkedList();
        treeMap.forEach((key,val)->{
            OrderUserAnalyzeVo orderUserAnalyzeVo = new OrderUserAnalyzeVo();
            FwUser fwUser = userService.getById(key);
            orderUserAnalyzeVo.setUserName(fwUser.getUserName());
            orderUserAnalyzeVo.setPhone(fwUser.getPhone());
            orderUserAnalyzeVo.setUserHeadImgUrl(fwUser.getHeadImage());
            orderUserAnalyzeVo.setCustomerVal(val);
            userOrderVos.addLast(orderUserAnalyzeVo);
        });
        orderAnalyzeVo.setOrderUserAnalyzeVos(userOrderVos);
        return orderAnalyzeVo;
    }

    @Override
    public List<OrderMoneyVo> manageOnlineOrder(String shopId, OrderManageQuery orderManageQuery) {
        List<OrderMoneyVo> orderMoneyVos =  orderService.manageOnlineOrder(shopId,orderManageQuery.getQueryRange(),orderManageQuery.getLimit());
        return orderMoneyVos;
    }

    @Override
    public List<OrderMoneyVo> manageOffOrder(String shopId, OrderManageQuery orderManageQuery) {
        Assert.isTrue( shopService.shopOff(shopId),"您还不是线下商户,您迷路了哦...");
        return offlineService.manageOffOrder(shopId,orderManageQuery.getQueryRange(),orderManageQuery.getLimit());
    }

    private boolean shopLookFunc(String yearQuery, ShopAnalyzeVo.ShopAnalyzeVoBuilder builder, Set<String> spuIds, String dataOffsetDate) {
        List<FwFootprint> toDayYearFootprints = fwFootprintService.list(Wrappers.<FwFootprint>lambdaQuery().in(FwFootprint::getItemId, spuIds).apply(StringUtils.isNotBlank(yearQuery), "  date_format(create_time,'%Y-%m-%d') = {0} ", yearQuery));
        builder.shopLookCount(toDayYearFootprints.size());
        // 计算波比
        List<FwFootprint> toWaiYearFootprints =  fwFootprintService.list(Wrappers.<FwFootprint>lambdaQuery().in(FwFootprint::getItemId, spuIds).apply(StringUtils.isNotBlank(yearQuery), "  date_format(create_time,'%Y-%m-%d') = {0} ", dataOffsetDate));
        // 默认正波比
        builder.shopLookMoveFlag(Boolean.TRUE);
        if (toWaiYearFootprints.size() > toDayYearFootprints.size())
            builder.shopLookMoveFlag(Boolean.FALSE);
        // 计算波比值
        builder.shopLookMoveVal(RandomUtils.mathNumber(NumberUtil.add(toWaiYearFootprints.size()),NumberUtil.add(toDayYearFootprints.size())).intValue());
    return true;
    }

    // 用户关注量
    private boolean shopLikeFunc(String shopId, String yearQuery, ShopAnalyzeVo.ShopAnalyzeVoBuilder builder, String dataOffsetDate) {
        List<FwUsjoin> toDayYearUsCount = usjoinService.list(Wrappers.<FwUsjoin>lambdaQuery()
                .eq(FwUsjoin::getShopId, shopId)
                .apply(StringUtils.isNotBlank(yearQuery), "  date_format(create_time,'%Y-%m-%d') = {0} ", yearQuery));

        builder.shopLikeCount(toDayYearUsCount.size());

        List<FwUsjoin> toWaiYearUsCount = usjoinService.list(Wrappers.<FwUsjoin>lambdaQuery()
                .eq(FwUsjoin::getShopId, shopId)
                .apply(StringUtils.isNotBlank(yearQuery), "  date_format(create_time,'%Y-%m-%d') = {0} ", dataOffsetDate));
        // 默认正波比
        builder.shopLickMoveFlag(Boolean.TRUE);
        if (toWaiYearUsCount.size() > toDayYearUsCount.size())
            builder.shopLickMoveFlag(Boolean.FALSE);

        // 计算波比值
        builder.shopLickMoveVal(RandomUtils.mathNumber(NumberUtil.add(toWaiYearUsCount.size()),NumberUtil.add(toDayYearUsCount.size())).intValue());
    return true;
    }

    // 计算评分
    private boolean orderSvg(String yearQuery, ShopAnalyzeVo.ShopAnalyzeVoBuilder builder, List<FwSpu> spuList, Set<String> spuIds) {
        builder.otherStars(Integer.valueOf(0));
        builder.oneStars(Integer.valueOf(0));
        builder.twoStars(Integer.valueOf(0));
        builder.threeStars(Integer.valueOf(0));
        builder.fourStars(Integer.valueOf(0));
        builder.fiveStars(Integer.valueOf(0));
        builder.evaluationCount(Integer.valueOf(0));
        if (!spuList.isEmpty()){
            List<FwEvaluation> evaluationList = evaluationService.list(Wrappers.<FwEvaluation>lambdaQuery()
                    .in(FwEvaluation::getItemId, spuIds).apply(StringUtils.isNotBlank(yearQuery), "  date_format(create_time,'%Y-%m-%d') = {0} ", yearQuery));
            if (!evaluationList.isEmpty()){
                builder.otherStars(Long.valueOf(evaluationList.parallelStream().filter(item -> Integer.valueOf(0).equals(item.getStarNum())).count()).intValue());
                builder.oneStars(Long.valueOf(evaluationList.parallelStream().filter(item -> Integer.valueOf(1).equals(item.getStarNum())).count()).intValue());
                builder.twoStars(Long.valueOf(evaluationList.parallelStream().filter(item -> Integer.valueOf(2).equals(item.getStarNum())).count()).intValue());
                builder.threeStars(Long.valueOf(evaluationList.parallelStream().filter(item -> Integer.valueOf(3).equals(item.getStarNum())).count()).intValue());
                builder.fourStars(Long.valueOf(evaluationList.parallelStream().filter(item -> Integer.valueOf(4).equals(item.getStarNum())).count()).intValue());
                builder.fiveStars(Long.valueOf(evaluationList.parallelStream().filter(item -> Integer.valueOf(5).equals(item.getStarNum())).count()).intValue());
                builder.evaluationCount(evaluationList.size());
            }
        }
        return true;
    }
}
